<template>
  <div>
    <h2>父组件</h2>
    <div>
      <h3>父组件中的数据：</h3>
      <div class="data-display">
        <p>文本值: <span>{{ text }}</span></p>
        <p>数字值: <span>{{ count }}</span></p>
        <p>选中状态: <span>{{ checked ? '是' : '否' }}</span></p>
      </div>
      
      <div class="controls">
        <button @click="resetValues">重置所有值</button>
      </div>
    </div>
    
    <!-- 
      使用 v-model 实现父子组件双向绑定
      1. 基本 v-model: v-model="text"
      2. 命名 v-model: v-model:count="count"
      3. 带修饰符的 v-model: v-model.trim="text"
    -->
    <Child 
      v-model="text"
      v-model:count="count"
      v-model:checked="checked"
    />
  </div>
</template>

<script lang="ts" setup>
/**
 * v-model 组件通信详解 - 父组件部分
 * 
 * 1. v-model 的本质：
 *    在 Vue 3 中，组件上的 v-model 是以下写法的简写：
 *    <Child 
 *      :modelValue="text"
 *      @update:modelValue="text = $event"
 *    />
 * 
 * 2. 多个 v-model 的使用：
 *    Vue 3 允许在一个组件上使用多个 v-model，通过命名方式区分：
 *    <Child 
 *      v-model="text"              // 默认绑定到 modelValue prop
 *      v-model:count="count"       // 绑定到 count prop
 *      v-model:checked="checked"   // 绑定到 checked prop
 *    />
 * 
 * 3. v-model 修饰符：
 *    可以使用修饰符来改变绑定行为：
 *    <Child v-model.trim="text" />  // 使用 trim 修饰符
 * 
 * 4. 使用场景：
 *    4.1 表单组件：如自定义输入框、选择器、日期选择器等
 *    4.2 需要双向数据流的组件：如对话框的可见状态、标签页的激活索引
 *    4.3 编辑器组件：如富文本编辑器、代码编辑器
 *    4.4 配置面板：用户可以实时调整并预览效果
 */

import { ref } from 'vue';
import Child from './child.vue';

// 定义响应式数据，用于 v-model 绑定
const text = ref('初始文本');
const count = ref(0);
const checked = ref(false);

// 重置所有值的方法
function resetValues() {
  text.value = '初始文本';
  count.value = 0;
  checked.value = false;
}

/**
 * 5. v-model 的优缺点：
 * 
 * 优点：
 * - 简化了父子组件间的双向数据流
 * - 代码更简洁，易于理解
 * - Vue 3 支持多个 v-model，更加灵活
 * 
 * 缺点：
 * - 可能导致数据流向不清晰
 * - 过度使用可能使应用状态难以追踪
 * - 需要子组件正确实现 props 和事件
 * 
 * 6. 最佳实践：
 *    6.1 仅在真正需要双向绑定的场景使用 v-model
 *    6.2 为自定义组件的 v-model 提供清晰的文档
 *    6.3 使用有意义的名称命名多个 v-model
 *    6.4 考虑使用计算属性在子组件中处理 v-model
 */
</script>

<style scoped>
/* 父组件样式 */
div {
  background: linear-gradient(to right, #8e2de2, #4a00e0);
  border-radius: 15px;
  padding: 30px;
  color: white;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  max-width: 800px;
  margin: 20px auto;
}

h2 {
  font-size: 28px;
  margin-bottom: 25px;
  text-align: center;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
  position: relative;
  padding-bottom: 15px;
}

h2::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100px;
  height: 3px;
  background-color: rgba(255, 255, 255, 0.5);
  border-radius: 3px;
}

h3 {
  font-size: 20px;
  margin-bottom: 15px;
  font-weight: 500;
}

.data-display {
  background-color: rgba(255, 255, 255, 0.1);
  padding: 15px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.data-display p {
  margin: 8px 0;
  font-size: 16px;
}

.data-display span {
  font-weight: bold;
  color: #f6d365;
  background-color: rgba(0, 0, 0, 0.2);
  padding: 2px 8px;
  border-radius: 4px;
  margin-left: 5px;
}

.controls {
  margin-top: 20px;
}

button {
  background-color: white;
  color: #8e2de2;
  border: none;
  padding: 10px 15px;
  border-radius: 8px;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

button:hover {
  background-color: #f0f0f0;
  color: #4a00e0;
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
</style>